package com.eshop.modules.cart.service.impl;

import java.lang.invoke.SerializedLambda;
import com.eshop.modules.order.service.dto.CountDto;
import java.io.IOException;
import com.eshop.utils.FileUtil;
import javax.servlet.http.HttpServletResponse;
import com.eshop.common.utils.QueryHelpPlus;
import com.eshop.modules.cart.service.dto.StoreCartDto;
import com.github.pagehelper.PageInfo;
import org.springframework.data.domain.Pageable;
import com.eshop.modules.cart.service.dto.StoreCartQueryCriteria;
import com.eshop.modules.activity.domain.StoreBargain;
import com.eshop.enums.ProductTypeEnum;
import com.eshop.modules.product.domain.StoreProduct;
import java.util.Date;
import com.eshop.modules.product.domain.StoreProductAttrValue;
import java.util.Iterator;
import java.util.LinkedHashMap;
import com.eshop.enums.ShopCommonEnum;
import java.io.Serializable;
import cn.hutool.core.util.ObjectUtil;
import com.eshop.modules.product.vo.StoreProductQueryVo;
import com.eshop.modules.cart.vo.StoreCartQueryVo;
import java.util.ArrayList;
import java.util.Arrays;
import cn.hutool.core.util.StrUtil;
import com.eshop.enums.CartTypeEnum;
import com.eshop.enums.OrderInfoEnum;
import java.util.Map;
import com.eshop.api.EshopException;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import java.util.Collection;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.function.Function;
import java.util.List;
import com.eshop.modules.user.service.UserService;
import com.eshop.modules.activity.service.StoreBargainService;
import com.eshop.modules.product.service.StoreProductAttrService;
import com.eshop.modules.product.service.StoreProductService;
import com.eshop.modules.activity.service.mapper.StoreCombinationMapper;
import com.eshop.modules.activity.service.mapper.StoreBargainMapper;
import com.eshop.modules.activity.service.mapper.StoreSeckillMapper;
import org.springframework.beans.factory.annotation.Autowired;
import com.eshop.dozer.service.IGenerator;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.stereotype.Service;
import com.eshop.modules.cart.service.StoreCartService;
import com.eshop.modules.cart.domain.StoreCart;
import com.eshop.modules.cart.service.mapper.StoreCartMapper;
import com.eshop.common.service.impl.BaseServiceImpl;

@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = { Exception.class })
public class StoreCartServiceImpl extends BaseServiceImpl<StoreCartMapper, StoreCart> implements StoreCartService
{
    @Autowired
    private IGenerator generator;
    @Autowired
    private StoreCartMapper yxStoreCartMapper;
    @Autowired
    private StoreSeckillMapper storeSeckillMapper;
    @Autowired
    private StoreBargainMapper storeBargainMapper;
    @Autowired
    private StoreCombinationMapper storeCombinationMapper;
    @Autowired
    private StoreProductService productService;
    @Autowired
    private StoreProductAttrService productAttrService;
    @Autowired
    private StoreBargainService storeBargainService;
    @Autowired
    private UserService userService;
    
    public void removeUserCart(final Long uid, final List<String> ids) {
        //转换成Long集合
        final List<Long> newids = ids.stream().map(Long::new).collect(Collectors.toList());
        LambdaQueryWrapper<StoreCart> wrapper = new LambdaQueryWrapper();
        wrapper.eq(StoreCart::getUid,uid).in(StoreCart::getId,newids);

        this.yxStoreCartMapper.delete((Wrappers.<StoreCart>lambdaQuery().eq(StoreCart::getUid, uid)).in(StoreCart::getId, newids));
    }

    public void changeUserCartNum(final Long cartId, final int cartNum, final Long uid) {
        //根据uid和购物车id去查
        final StoreCart cart = ((this.lambdaQuery().eq(StoreCart::getUid, uid)).eq(StoreCart::getId, cartId)).one();
        if (cart == null) {
            throw new EshopException("购物车不存在");
        }
        if (cartNum <= 0) {
            throw new EshopException("库存错误");
        }
        //根据productId和skuId检查库存
        final int stock = this.productService.getProductStock(cart.getProductId(), cart.getProductAttrUnique(), "");
        if (stock < cartNum) {
            throw new EshopException("该产品库存不足" + cartNum);
        }
        //如果要修改的购物车商品数量和之前数量没区别就打回
        if (cartNum == cart.getCartNum()) {
            return;
        }
        final StoreCart storeCart = new StoreCart();
        storeCart.setCartNum(cartNum);
        storeCart.setId(cartId);
        this.yxStoreCartMapper.updateById(storeCart);
    }

    public Map<String, Object> getUserProductCartList(final Long uid, final String cartIds, final Integer status) {
        final LambdaQueryWrapper<StoreCart> wrapper = new LambdaQueryWrapper();
        //获取当前用户的，没有支付的订单，且根据订单id倒序
        ((wrapper.eq(StoreCart::getUid, uid)).eq(StoreCart::getIsPay, OrderInfoEnum.PAY_STATUS_0.getValue())).orderByDesc(StoreCart::getId);
        //如果没有传status过来，就设置查询条件去查询加入购物车的商品，而不是加入购物车并购买的商品
        if (status == null) {
            //0是加入购物车   1是加入购物车直接购买
            wrapper.eq(StoreCart::getIsNew, CartTypeEnum.NEW_0.getValue());
        }
        //只要传过来的cartIds不是空的，就查询指定cartId
        if (StrUtil.isNotEmpty((CharSequence)cartIds)) {
            wrapper.in(StoreCart::getId, Arrays.asList(cartIds.split(",")));
        }
        final List<StoreCart> carts = (List<StoreCart>)this.yxStoreCartMapper.selectList(wrapper);
        //还是要转化成vo对象，然后有一个valid集合，以及invalid集合
        final List<StoreCartQueryVo> valid = new ArrayList<StoreCartQueryVo>();
        final List<StoreCartQueryVo> invalid = new ArrayList<StoreCartQueryVo>();
        for (final StoreCart storeCart : carts) {
            StoreProductQueryVo storeProduct = null;
            //判断查出来的购物车商品是拼团还是秒杀，或者砍价的，亦或者是普通商品，如果是的话就从对应地方去查询出数据
            if (storeCart.getCombinationId() != null && storeCart.getCombinationId() > 0L) {
                storeProduct = (StoreProductQueryVo)ObjectUtil.clone(this.storeCombinationMapper.combinatiionInfo(storeCart.getCombinationId()));
            }
            else if (storeCart.getSeckillId() != null && storeCart.getSeckillId() > 0L) {
                storeProduct = (StoreProductQueryVo)ObjectUtil.clone(this.storeSeckillMapper.seckillInfo(storeCart.getSeckillId()));
            }
            else if (storeCart.getBargainId() != null && storeCart.getBargainId() > 0L) {
                storeProduct = (StoreProductQueryVo)ObjectUtil.clone(this.storeBargainMapper.bargainInfo(storeCart.getBargainId()));
            }
            else {
                storeProduct = (StoreProductQueryVo)ObjectUtil.clone(this.productService.getStoreProductById(storeCart.getProductId()));
            }
            //直接将查询出来的storeProduct转换成StoreCartQueryVo对象，但是里面还是有一部分属性转不过去，所以需要后面手动赋值
            final StoreCartQueryVo storeCartQueryVo = (StoreCartQueryVo)this.generator.convert(storeCart, (Class)StoreCartQueryVo.class);
            //如果查询出来的storeProduct对象为null，就说明在原来的商品表或者秒杀表里面等等已经被删除了
            //所以要把这个购物车商品从表中删除掉
            if (ObjectUtil.isNull(storeProduct)) {
                this.removeById((Serializable)storeCart.getId());
            }
            //如果说该商品已经设置了是不显示或者库存为0或者该购物车商品的sku值为空，就加入到无效商品集合中
            else if (ShopCommonEnum.SHOW_0.getValue().equals(storeProduct.getIsShow()) || (storeProduct.getStock() == 0 && StrUtil.isEmpty((CharSequence)storeCart.getProductAttrUnique()))) {
                storeCartQueryVo.setProductInfo(storeProduct);
                invalid.add(storeCartQueryVo);
            }
            //该商品的sku值不为空
            else if (StrUtil.isNotEmpty((CharSequence)storeCart.getProductAttrUnique())) {
                //查询该商品的sku详细信息，比如库存，原价啥的
                final StoreProductAttrValue productAttrValue = this.productAttrService.uniqueByAttrInfo(storeCart.getProductAttrUnique());
                //如果该sku不存在，或者sku的库存为0，那么就是invalid商品
                if (ObjectUtil.isNull(productAttrValue) || productAttrValue.getStock() == 0) {
                    storeCartQueryVo.setProductInfo(storeProduct);
                    invalid.add(storeCartQueryVo);
                }
                //否则就是有效商品
                else {
                    //给storeProduct设置上他对应的sku值
                    storeProduct.setAttrInfo(productAttrValue);
                    //然后再将storeProduct设置到vo里面
                    storeCartQueryVo.setProductInfo(storeProduct);
                    //根据当前用户等级以及商品原价，计算出vip价格
                    double vipPrice = this.userService.setLevelPrice(productAttrValue.getPrice().doubleValue(), uid);
                    //判断该商品是否为砍价，拼团，秒杀商品，这种商品是不会打折的，所以直接获取价格
                    if (storeCart.getBargainId() > 0L) {
                        vipPrice = storeProduct.getPrice().doubleValue();
                    }
                    if (storeCart.getCombinationId() > 0L) {
                        vipPrice = productAttrValue.getPinkPrice().doubleValue();
                    }
                    if (storeCart.getSeckillId() > 0L) {
                        vipPrice = productAttrValue.getSeckillPrice().doubleValue();
                    }
                    //接着把真实需要付的价格，也就是vip价格设置到vo里面
                    storeCartQueryVo.setTruePrice(vipPrice);
                    //虽然这里设置的是vip真实价格，但是这个取出来的值就是sku原价
                    storeCartQueryVo.setVipTruePrice(productAttrValue.getPrice().doubleValue());
                    //设置成本价
                    storeCartQueryVo.setCostPrice(productAttrValue.getCost().doubleValue());
                    //设置库存
                    storeCartQueryVo.setTrueStock(productAttrValue.getStock());
                    //添加到valid集合里面
                    valid.add(storeCartQueryVo);
                }
            }
            //这种情况也算有效商品把，虽然sku的值为空
            else {
                //直接计算出vip价格
                double vipPrice2 = this.userService.setLevelPrice(storeProduct.getPrice().doubleValue(), uid);
                //如果是拼团，秒杀，砍价中的任何一个，就不打折
                if (storeCart.getCombinationId() > 0L || storeCart.getSeckillId() > 0L || storeCart.getBargainId() > 0L) {
                    vipPrice2 = storeProduct.getPrice().doubleValue();
                }
                //然后直接设置进去就行了
                storeCartQueryVo.setTruePrice(vipPrice2);
                storeCartQueryVo.setVipTruePrice(0.0);
                storeCartQueryVo.setCostPrice(storeProduct.getCost().doubleValue());
                storeCartQueryVo.setTrueStock(storeProduct.getStock());
                storeCartQueryVo.setProductInfo(storeProduct);
                valid.add(storeCartQueryVo);
            }
        }
        //最终返回有效和无效的购物车商品集合就行了
        final Map<String, Object> map = new LinkedHashMap<String, Object>();
        map.put("valid", valid);
        map.put("invalid", invalid);
        return map;
    }

    public int getUserCartNum(final Long uid) {
        return this.yxStoreCartMapper.cartSum(uid);
    }

    /**
     * 流程总结
     * 先检查产品库存
     * 查询该用户的购物车是否已经有该商品了
     * 有就修改cartNum，没有就插入数据
     */
    @Override
    public long addCart(final Long uid, final Long productId, final Integer cartNum, final String productAttrUnique, final Integer isNew, final Long combinationId, final Long seckillId, final Long bargainId) {
        //检查产品库存 检查的时候分类检查 看是否为拼团，秒杀，砍价商品，这三个商品有自己的库存
        this.checkProductStock(uid, productId, cartNum, productAttrUnique, combinationId, seckillId, bargainId);
        //构造查询条件
        final LambdaQueryWrapper<StoreCart> wrapper = (LambdaQueryWrapper<StoreCart>)new LambdaQueryWrapper();
        //uid，未支付，产品ID，是否为立即购买，uniqueId，拼团ID，砍价ID,秒杀ID
        (((((((((wrapper.eq(StoreCart::getUid, uid)).eq(StoreCart::getIsPay, OrderInfoEnum.PAY_STATUS_0.getValue()))
                .eq(StoreCart::getProductId, productId))
                .eq(StoreCart::getIsNew, isNew))
                .eq(StoreCart::getProductAttrUnique, productAttrUnique))
                .eq(StoreCart::getBargainId, bargainId))
                .eq(StoreCart::getCombinationId, combinationId))
                .eq(StoreCart::getSeckillId, seckillId)).orderByDesc(StoreCart::getId))
                .last("limit 1");
        //查询出一个StoreCart
        final StoreCart cart = (StoreCart)this.yxStoreCartMapper.selectOne((Wrapper)wrapper);
        //将用户添加的商品封装成storeCart
        final StoreCart storeCart = StoreCart.builder().cartNum(cartNum).productAttrUnique(productAttrUnique)
                .productId(productId).bargainId(bargainId).combinationId(combinationId)
                .seckillId(seckillId).isNew(isNew).uid(uid).build();
        //如果后端查出来当前cart之前就存在
        if (cart != null) {
            //而且是加入购物车，而不是加入购物车直接买
            if (CartTypeEnum.NEW_0.getValue().equals(isNew)) {
                //直接累加后修改数量就行了
                storeCart.setCartNum(cartNum + cart.getCartNum());
            }
            storeCart.setId(cart.getId());
            this.yxStoreCartMapper.updateById(storeCart);
        }
        else {
            this.yxStoreCartMapper.insert(storeCart);
        }
        return storeCart.getId();
    }

    //检查产品库存，也可以说是sku库存
    public void checkProductStock(final Long uid, final Long productId, final Integer cartNum, final String productAttrUnique, final Long combinationId, final Long seckillId, final Long bargainId) {
        final Date now = new Date();
        //注意拼团和秒杀以及砍价商品有自己的库存
        //判断是不是拼团商品 store_product_attr_value表中查数据
        if (combinationId != null && combinationId > 0L) {
            final StoreProduct product = (StoreProduct)((this.productService.lambdaQuery().eq(StoreProduct::getId, productId)).eq(StoreProduct::getIsShow, ShopCommonEnum.SHOW_1.getValue())).one();
            if (product == null) {
                throw new EshopException("该产品已下架或删除");
            }
            final int stock = this.productService.getProductStock(productId, productAttrUnique, ProductTypeEnum.PINK.getValue());
            if (stock < cartNum) {
                throw new EshopException(product.getStoreName() + "库存不足" + cartNum);
            }
        }
        //判断是不是秒杀商品 store_product_attr_value表中查数据
        else if (seckillId != null && seckillId > 0L) {
            final StoreProduct product = (StoreProduct)((this.productService.lambdaQuery().eq(StoreProduct::getId, productId)).eq(StoreProduct::getIsShow, ShopCommonEnum.SHOW_1.getValue())).one();
            if (product == null) {
                throw new EshopException("该产品已下架或删除");
            }
            final int stock = this.productService.getProductStock(productId, productAttrUnique, ProductTypeEnum.SECKILL.getValue());
            if (stock < cartNum) {
                throw new EshopException(product.getStoreName() + "库存不足" + cartNum);
            }
        }
        //判断是否为砍价商品 store_bargain表中查数据
        else if (bargainId != null && bargainId > 0L) {
            final StoreBargain storeBargain = (StoreBargain)((((this.storeBargainService.lambdaQuery().eq(StoreBargain::getId, bargainId)).eq(StoreBargain::getStatus, ShopCommonEnum.IS_STATUS_1.getValue())).le(StoreBargain::getStartTime, now)).ge(StoreBargain::getStopTime, now)).one();
            if (storeBargain == null) {
                throw new EshopException("该产品已下架或删除");
            }
            if (storeBargain.getStock() < cartNum) {
                throw new EshopException("该产品库存不足");
            }
        }
        //到这条分支的话，就是普通商品了
        else {
            final StoreProduct product = (StoreProduct)((this.productService.lambdaQuery().eq(StoreProduct::getId, productId)).eq(StoreProduct::getIsShow, ShopCommonEnum.SHOW_1.getValue())).one();
            if (product == null) {
                throw new EshopException("该产品已下架或删除");
            }
            final int stock = this.productService.getProductStock(productId, productAttrUnique, "");
            if (stock < cartNum) {
                throw new EshopException(product.getStoreName() + "库存不足" + cartNum);
            }
        }
    }
    
    public Map<String, Object> queryAll(final StoreCartQueryCriteria criteria, final Pageable pageable) {
        this.getPage(pageable);
        final PageInfo<StoreCart> page = (PageInfo<StoreCart>)new PageInfo((List)this.queryAll(criteria));
        final Map<String, Object> map = new LinkedHashMap<String, Object>(2);
        map.put("content", this.generator.convert(page.getList(), (Class)StoreCartDto.class));
        map.put("totalElements", page.getTotal());
        return map;
    }
    
    public List<StoreCart> queryAll(final StoreCartQueryCriteria criteria) {
        return (List<StoreCart>)(this.baseMapper).selectList(QueryHelpPlus.getPredicate(StoreCart.class, criteria));
    }
    
    public void download(final List<StoreCartDto> all, final HttpServletResponse response) throws IOException {
        final List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        for (final StoreCartDto yxStoreCart : all) {
            final Map<String, Object> map = new LinkedHashMap<String, Object>();
            map.put("用户ID", yxStoreCart.getUid());
            map.put("类型", yxStoreCart.getType());
            map.put("商品ID", yxStoreCart.getProductId());
            map.put("商品属性", yxStoreCart.getProductAttrUnique());
            map.put("商品数量", yxStoreCart.getCartNum());
            map.put("添加时间", yxStoreCart.getAddTime());
            map.put("0 = 未购买 1 = 已购买", yxStoreCart.getIsPay());
            map.put("是否删除", yxStoreCart.getIsDel());
            map.put("是否为立即购买", yxStoreCart.getIsNew());
            map.put("拼团id", yxStoreCart.getCombinationId());
            map.put("秒杀产品ID", yxStoreCart.getSeckillId());
            map.put("砍价id", yxStoreCart.getBargainId());
            list.add(map);
        }
        FileUtil.downloadExcel((List)list, response);
    }
    
    public List<CountDto> findCateName() {
        return this.yxStoreCartMapper.findCateName();
    }
}
